package llvmir.value.structure;

import java.util.List;
import llvmir.value.Value;
import java.util.ArrayList;

public class Module extends Value {
    private static Module instance;
    private List<Value> functions;
    private List<Value> globalVariables;
    private Function mainFunction;

    private Module() {
        // 编译器单文件结构，时刻只有一个module
        super("module", null);
        functions = new ArrayList<>();
        globalVariables = new ArrayList<>();
    }

    public static Module getInstance() {
        if (instance == null) {
            instance = new Module();
        }
        return instance;
    }

    public void addFunction(Function function) {
        // 不考虑重复定义
        functions.add(function);
    }

    public void addGlobalVariable(GlobalVariable globalVariable) {
        // 不考虑重复定义
        globalVariables.add(globalVariable);
    }

    public void setMainFunction(Function mainFunction) {
        this.mainFunction = mainFunction;
    }

    public Function getMainFunction() {
        return mainFunction;
    }

    public List<Value> getGlobalVariables() {
        return globalVariables;
    }

    public List<Value> getFunctions() {
        return functions;
    }

    public Function searchFunction(String name) {
        for (Value function : functions) {
            if (function.getName().equals(name)) {
                return (Function) function;
            }
        }
        return null;

    }

    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        for (Value globalVariable : globalVariables) {
            sb.append(globalVariable).append("\n");
        }
        sb.append("\ndeclare i32 @getint()\n" +
                "declare i32 @getchar()\n" +
                "declare void @putint(i32)\n" +
                "declare void @putch(i32)\n" +
                "declare void @putstr(i8*)\n\n");
        for (Value function : functions) {
            sb.append(function).append("\n");
        }
        sb.append(mainFunction);

        return sb.toString();
    }
}
